from pyqtgraph.Qt import QtGui, QtCore
#from PyQt4 import QtGui, QtCore
import numpy
import pyqtgraph
import os
import datetime
import time
import itertools


#TODO  pyqtgraph/graphicsItems/ViewBox/ViewBoxMenu.py 
	#I want to add things and remove things from the right click menu.
	    #I want to remove the export stuff
	    #I want to add a  'show everything' function

#TODO plot displays time in seconds since the program was opened.  Let's try to make it in real-time.
	#At least explain somewhere that this is the case. 


class MyPlot(pyqtgraph.PlotWidget):
	sigPlotClosed = QtCore.pyqtSignal()
	sigNewLowerBound = QtCore.pyqtSignal(float)
	def __init__(self, tite):  
		super(MyPlot, self).__init__(title = tite)
		self.enableAutoRange('y' , 1)
		self.viewBox = self.getViewBox()
		self.viewBox.sigRangeChangedManually.connect(self.findSignal)
		menu = self.getMenu()
		menuitmes = [k for k,v in menu.__dict__.items() ]#if isinstance(v, pyqtgraph.QtGui.QWidget)]
		    
	def closeEvent(self, ev):
		self.sigPlotClosed.emit()

	def findSignal(self):
		lowerBound = self.viewBox.getState()['targetRange'][0][0]
		self.sigNewLowerBound.emit(lowerBound)

class PlotFather(QtGui.QMainWindow):  #now this is obsolete!... damn it!  
	sigPlotExportSuccess = QtCore.pyqtSignal( 'QString' )
	def __init__(self, statThread, timer, downSample = 0): #, statThread, timer):   
		super(PlotFather, self).__init__()
		#plt.plotItem.ctrlMenu = None  # get rid of 'Plot Options'
		#>>> plt.scene().contextMenu = None  # get rid of 'Export'
		self.downSample = downSample
		self.statThread = statThread
		self.timer = timer
		self.colorList = ['b', 'g', 'r', 'c','m', 'y', 'k', 'w']
		self.timer.timeout.connect(self.update)
		self.lbl = "plot"

	def export(self):
		#will export the function to the current working directory and then move it to /plots, a directory within the cwd
		cwd = os.getcwd()
		newpath = cwd + "/plots"
		if not os.path.exists(newpath): 
			os.makedirs(newpath)
		exporter = pyqtgraph.exporters.ImageExporter.ImageExporter(self.plot.plotItem)
		name = '%s.png' % time.time()
		exporter.export(name)    
		newName = "./plots/%s" %name
		os.rename(name, newName)
		self.sigPlotExportSuccess.emit(newName)
		#print "plot exported"

	def getArray(self, plotTuple):
		exec 'array = self.statThread.dataDict[plotTuple[0]].%s' %plotTuple[1]
		return array    #[self.downSample:]

	def getType(self, plotTuple):
		exec 'array = self.statThread.dataDict[plotTuple[0]].%s' %plotTuple[1] 
		return type(array[0])

	def getDownSample(self):
		return self.downSample

	def setDownSample(self, newDownSample): 
		self.downSample = newDownSample


class multiPlot(PlotFather):
	'''If the xAxis is user determined then it is a tuple otherwise it xAxis is a string'''

	def __init__(self, statThread, timer,  plotThese, title = "stop here", xAxis = 'clockIn'):
		super(multiPlot, self).__init__(statThread, timer)
		self.statThread     = statThread
		self.timer   = timer
		self.curve          = dict()
		self.xAxis = xAxis
		self.title = title

		if self.xAxis == 'clockIn':
			self.plotList = plotThese
			self.userDefdAxis = False
		else:
		    if self.getType(xAxis) is list or self.getType(xAxis) is tuple:
		        return
		    else:
		        self.plotList = [x for x in plotThese if x != self.xAxis]
		        self.userDefdAxis = True
		self.setupPlot() 

	def setupPlot(self):
		numplot = 0
		self.plot = MyPlot(self.title)
		self.plot.plotItem.ctrlMenu = None  # get rid of 'Plot Options'
		self.plot.scene().contextMenu = None  # get rid of 'Export'
		self.plot.sigNewLowerBound.connect(self.newLowerBound)
		self.plot.addLegend()

		for each in self.plotList: 
			typeOf = self.getType(each)
			if typeOf is list or typeOf is tuple:
				self.addVector(each, numplot)
			else:
				if self.userDefdAxis:#determine axis, 
					xAxis = self.getArray(self.xAxis)
				else:
					xAxis = self.getArray((each[0], self.xAxis))#get

				att = each[1]
				self.curve[att] = self.plot.plot(x = xAxis, y = self.getArray(each),\
		                        pen = self.colorList[numplot], name = str(att))
				numplot = numplot +1
		 
		if self.userDefdAxis:#because 'clockIn' isn't a good label
		    self.lbl = str(self.xAxis)
		else:
		    self.lbl = 'time'

		#self.plot.setWindowTitle('Plo')
		self.plot.setLabel('bottom', self.lbl)
		self.plot.show()


		#TODO: this makes very little sense, refactor and prove correctness
		#we check for truth of .userDefAxis a lot, can we factor this out so we only check once?
		#if self.userDefdAxis:
			#what does this if do?
		#	xAxis = self.getArray(self.xAxis)
		#	self.plot.enableAutoRange(axis=self.plot.viewBox.XAxis, enable=True, x=None, y=1) 
	def addVector(self, vector, numplot):
		data = self.getArray(vector)
		if self.userDefdAxis:#determine axis
		    xAxis = self.getArray(self.xAxis)
		else:
		    xAxis = self.getArray((vector[0],'clockIn'))[1:]
		for i in range(0, len(self.getArray(vector)[0])):         
		    eachArray = [row[i] for row in itertools.islice(data, 1, None)]
		    self.curve[i] = self.plot.plot(x=xAxis, y=eachArray ,pen = self.colorList[numplot % 8 ], name = str(vector[1] + ' '+str(i)) )
		    numplot = numplot +1

	def update(self):
		for each in self.plotList:			

			typeOf = self.getType(each)
			if typeOf is list or typeOf is tuple:
				#print "its a list!!"
				if self.userDefdAxis:#determine axis
					xAxis = self.getArray(self.xAxis)
				else:
					xAxis = self.getArray((each[0],'clockIn'))[1:]

				data = self.getArray(each)
				for i in range(0, len(self.getArray(each)[0])):
					eachArray = [row[i] for row in itertools.islice(data, 1, None)]
					self.curve[i].setData(xAxis[self.downSample:], eachArray[self.downSample:], clear = True)
			else:
				if self.userDefdAxis:#axis is clock in
					xAxis = self.getArray(self.xAxis)
				else:
					xAxis = self.getArray((each[0], self.xAxis))
				self.curve[each[1]].setData(xAxis[self.downSample:], self.getArray(each)[self.downSample:], clear = True)
		
		dataUpperBound = xAxis[-1]
		viewBoxUpperBound =  self.plot.viewBox.getState()['viewRange'][0][1]

		if dataUpperBound > viewBoxUpperBound:
			self.plot.enableAutoRange(axis=self.plot.viewBox.XAxis, enable=True, x=None, y=None)

	def newLowerBound(self, lowerBound):

		#deals with when the user manually pans the plot over,  
		if not self.userDefdAxis: #the axis is not user defined, it is 'clockIn'
		    xAxis = self.getArray((self.plotList[0][0],'clockIn'))[1:]
		    i = 0
		    while lowerBound > xAxis[i]:
		        i = i+1

		    self.setDownSample(i)

		else: #the x-axis is user defined.  
	   	#TODO this has not been implemented:
		    xAxis = self.getArray(self.xAxis)[1:]

		self.plot.enableAutoRange(True)
		








